package log;

import java.util.Date;

import org.xml.sax.Attributes;
import org.xml.sax.helpers.DefaultHandler;

import prefuse.data.Node;
import prefuse.data.Table;
import prefuse.data.Tree;
import prefuse.data.parser.DataParseException;
import prefuse.data.parser.DataParser;
import prefuse.data.parser.ParserFactory;

public class TreeHandler extends DefaultHandler implements Constantes {


	private ParserFactory m_pf = ParserFactory.getDefaultFactory();
	
	private Table m_nodes = null;
    private Tree m_tree = null;
    
    private Node m_activeNode = null;
    private boolean m_inSchema = true;
    
    public TreeHandler() {
    	startDocument();
	}
    
    public void startDocument() {
        m_tree = new Tree();
        m_nodes = m_tree.getNodeTable();
        Class t = parseType("String");
//        m_nodes.addColumn(ID, t);
        m_nodes.addColumn(NODE, t);
        m_nodes.addColumn(AGENT_STATE, t);
    }
    
    private void schemaCheck() {
        if ( m_inSchema ) {
            m_inSchema = false;
        }
    }
    
    public void endElement(String namespaceURI, String localName, String qName) {
        if ( qName.equals(BRANCH) || qName.equals(LEAF) ) {
            m_activeNode = m_activeNode.getParent();
        }
    }
    
    public void startElement(String namespaceURI, String localName,
                             String qName, Attributes atts) {           
  if ( qName.equals(BRANCH) || qName.equals(LEAF) ) {
            schemaCheck();
            
            // parse a node element
            Node n;
            if ( m_activeNode == null ) {
                n = m_tree.addRoot();
            } else {
                n = m_tree.addChild(m_activeNode);
            }
            m_activeNode = n;
        }
        else if ( qName.equals(NODE) ) {
            // parse an attribute
            parseAttribute(atts);
        } else if(qName.equals(AGENT_STATE)){
        	// parsea el estado del agente.
        	parseAgentState(atts);
        }
    }
    
    protected void parseAgentState(Attributes atts) {
		StringBuilder sb = new StringBuilder();
		for(int i =0; i<atts.getLength();i++){
        	sb.append(atts.getQName(i));
        	sb.append("=");
        	sb.append(atts.getValue(i));
        	sb.append("  ");
        	if(i != atts.getLength()-1)
        		sb.append("\n");
        }
		System.out.println("------------------------------");
		System.out.println(sb.toString());
		System.out.println("------------------------------");
		
		m_activeNode.set(AGENT_STATE, sb.toString());
	}
    
    protected void parseAttribute(Attributes atts) {
        String alName, id = null, action = null;
        for ( int i = 0; i < atts.getLength(); i++ ) {
            alName = atts.getQName(i);
            if ( alName.equals(ID) ) {
                id = atts.getValue(i);
            } else if ( alName.equals(ACTION) ) {
                action = atts.getValue(i);
            }
        }
        if ( id == null || action == null ) {
            System.err.println("Attribute under-specified");
            return;
        }

        try {
            //Object val = parse(value, m_nodes.getColumnType(name));
        	StringBuilder sb = new StringBuilder();
        	sb.append(id);
        	sb.append("\n");
        	sb.append(action);
            m_activeNode.set(NODE, sb.toString());
        } catch ( Exception e ) {
            throw new RuntimeException(e);
        }
    }
    
    protected Object parse(String s, Class type)
        throws DataParseException
    {
        DataParser dp = m_pf.getParser(type);
        return dp.parse(s);
    }
    
    protected Class parseType(String type) {
        type = Character.toUpperCase(type.charAt(0)) +
               type.substring(1).toLowerCase();
        if ( type.equals(INT) || type.equals(INTEGER) ) {
            return int.class;
        } else if ( type.equals(LONG) ) {
            return long.class;
        } else if ( type.equals(FLOAT) ) {
            return float.class;
        } else if ( type.equals(DOUBLE) || type.equals(REAL)) {
            return double.class;
        } else if ( type.equals(BOOLEAN) ) {
            return boolean.class;
        } else if ( type.equals(STRING) ) {
            return String.class;
        } else if ( type.equals(DATE) ) {
            return Date.class;
        } else {
            throw new RuntimeException("Unrecognized data type: "+type);
        }
    }
    
    public Tree getTree() {
        return m_tree;
    }
}
